package com.stone.design.mode.pipeline.netty.context;

import com.stone.design.mode.pipeline.netty.handler.ChannelHandler;
import com.stone.design.mode.pipeline.netty.handler.in.ChannelInboundHandler;
import com.stone.design.mode.pipeline.netty.pipeline.ChannelOutboundInvoker;
import com.stone.design.mode.pipeline.netty.pipeline.ChannelPipeline;
import com.stone.design.mode.pipeline.netty.pipeline.DefaultChannelPipeline;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Executor;

import static com.stone.design.mode.pipeline.netty.context.ChannelHandlerMask.*;

/**
 * 抽象context，将context的公共方法在这里进行抽取实现
 * context也可以从当前节点发起入站或出站的事件传播
 *
 * @author wenpan 2024/01/21 17:23
 */
@Slf4j
public abstract class AbstractChannelHandlerContext implements ChannelHandlerContext {

    /**
     * handler名称
     */
    private final String name;
    /**
     * 下一个context节点
     */
    public volatile AbstractChannelHandlerContext next;
    /**
     * 上一个context节点
     */
    public volatile AbstractChannelHandlerContext prev;
    /**
     * 执行掩码
     */
    private final int executionMask;
    /**
     * 该context里的方法需要在哪个线程池里执行
     */
    private final Executor executor;
    /**
     * handler在pipeline的状态（也可以说是context的状态）
     */
    private final int handlerState = 1;
    /**
     * 所属的pipeline
     */
    private final DefaultChannelPipeline pipeline;

    public AbstractChannelHandlerContext(String name,
                                         DefaultChannelPipeline pipeline,
                                         Executor executor,
                                         Class<? extends ChannelHandler> handlerClass) {
        this.name = name;
        // 计算该handler的掩码
        executionMask = mask(handlerClass);
        this.executor = executor;
        this.pipeline = pipeline;
    }

    @Override
    public Executor executor() {
        return executor;
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public ChannelPipeline pipeline() {
        return pipeline;
    }

    @Override
    public ChannelHandlerContext fireChannelRegistered() {
        // 从当前节点开始向后查找，查找下一个具有执行能力的handler
        AbstractChannelHandlerContext contextInbound = findContextInbound(MASK_CHANNEL_REGISTERED);
        invokeChannelRegistered(contextInbound);
        return this;
    }

    @Override
    public ChannelHandlerContext fireChannelActive() {
        // 从当前节点开始向后查找，找到下一个具有执行权限的context
        AbstractChannelHandlerContext contextInbound = findContextInbound(MASK_CHANNEL_ACTIVE);
        // 执行context的方法
        invokeChannelActive(contextInbound);
        return this;
    }

    /**
     * 在pipeline上传播flush时间
     */
    @Override
    public ChannelHandlerContext flush() {
        // TODO 这里可以做一些事情
        // 从当前节点开始向前查找，找到下一个能执行flush操作的节点
        AbstractChannelHandlerContext next = findContextOutbound(MASK_FLUSH);
        // 执行next的flush
        invokeFlush(next);
        return this;
    }

    /**
     * 执行context的flush方法
     */
    public static void invokeFlush(AbstractChannelHandlerContext next) {
        Executor executor = next.executor();
        if (executor == null) {
            // 调用该节点的flush方法
            next.invokeFlush();
        } else {
            // 如果给节点指定了自己的线程池，则提交到线程池执行
            executor.execute(next::invokeFlush);
        }
    }

    /**
     * 具体执行某个context里的handler的flush方法
     */
    private void invokeFlush() {
        // 执行该handler的 flush 方法
        try {
            ((ChannelOutboundInvoker) handler()).flush();
        } catch (Exception e) {
            log.error("invokeFlush error.", e);
        }
    }

    /**
     * 执行context上的 channelActive 方法
     */
    public static void invokeChannelActive(AbstractChannelHandlerContext next) {
        Executor executor = next.executor();
        // 如果当前线程是reactor线程，则直接执行，否则则封装成一个任务提交到reactor线程队列等待reactor线程执行
        if (executor == null) {
            next.invokeChannelActive();
        } else {
            executor.execute(next::invokeChannelActive);
        }
    }

    private void invokeChannelActive() {
        // 执行该handler的channelActive方法
        try {
            ((ChannelInboundHandler) handler()).channelActive(this);
        } catch (Exception e) {
            log.error("invokeChannelActive error.", e);
        }
    }

    /**
     * 执行（响应）ChannelRegistered
     */
    public static void invokeChannelRegistered(AbstractChannelHandlerContext next) {
        Executor executor = next.executor();
        if (executor == null) {
            // 使用当前线程来执行
            next.invokeChannelRegistered();
        } else {
            // 使用该handler指定的线程池来执行
            executor.execute(next::invokeChannelRegistered);
        }
    }

    private void invokeChannelRegistered() {
        // 回调context里的handler的channelRegistered方法，是否还要在pipeline上继续传播取决于handler里是否有继续传播
        try {
            ((ChannelInboundHandler) handler()).channelRegistered(this);
        } catch (Exception e) {
            log.error("invokeChannelRegistered error.", e);
        }
    }

    /**
     * 在pipeline上向后查找下一个合适的入站handler
     */
    private AbstractChannelHandlerContext findContextInbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        do {
            // 向后查找下一个ChannelHandler
            ctx = ctx.next;
        } while (skipContext(ctx, mask, MASK_ONLY_INBOUND));
        return ctx;
    }

    /**
     * 在pipeline上向前查找下一个合适的出站处理器
     */
    private AbstractChannelHandlerContext findContextOutbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        //获取当前ChannelHandler的executor
        do {
            //向前查找获取前一个ChannelHandler
            ctx = ctx.prev;
            //判断前一个ChannelHandler是否具有响应 mask 事件的资格
        } while (skipContext(ctx, mask, MASK_ONLY_OUTBOUND));
        return ctx;
    }

    /**
     * 判断是否应该跳过该ctx
     */
    private static boolean skipContext(AbstractChannelHandlerContext ctx,
                                       int mask,
                                       int onlyMask) {
        return (ctx.executionMask & (onlyMask | mask)) == 0;
    }
}
